In [1]:
import time
In [11]:
%%time

time.sleep(.138)
CPU times: user 446 µs, sys: 1 µs, total: 447 µs
Wall time: 138 ms
In [20]:
%%time

time.sleep(.000639 * 10)
CPU times: user 311 µs, sys: 0 ns, total: 311 µs
Wall time: 6.52 ms
In [28]:
class Symbol(str):
    "Class to define symbols, which should be unique items"
    def __repr__(self):
        return str.__repr__(self)[1:-1] # don't show quotation marks
    
EmptyList = Symbol("()")
void = Symbol("<void>")
        
class Cons(object):
    "A cell/link used to construct linked-list"
    def __init__(self, car, cdr):
        self.car = car
        self.cdr = cdr
    def __repr__(self):
        if self.car == "closure-exp":
            return "#<procedure>"
        retval = ""
        current = self
        while current is not EmptyList and isinstance(current, Cons):
            if retval != "":
                retval += " "
            retval += str(current.car) # recursion here!
            current = current.cdr
        if current is not EmptyList:
            retval += " . " + str(current)
        return "(%s)" % retval
             
class String(str):
    "Class to wrap strings so that we can define repr"
    def __repr__(self):
        return '"%s"' % str.__repr__(self)[1:-1]
    def __str__(self):
        return self.__repr__()

def List(*args):
    "Create a linked-list of items"
    retval = EmptyList
    for arg in reversed(args):
        retval = cons(arg, retval)
    return retval
        
def car(exp):
    return exp.car
def cadr(exp):
    return exp.cdr.car
def caddr(exp):
    return exp.cdr.cdr.car
def cadddr(exp):
    return exp.cdr.cdr.cdr.car

def cdr(exp):
    return exp.cdr
def cddr(exp):
    return exp.cdr.cdr
def cdddr(exp):
    return exp.cdr.cdr.cdr
def cddddr(exp):
    return exp.cdr.cdr.cdr.cdr

def cons(item1, item2):
    return Cons(item1, item2)

def length(item, handler):
    current = item
    count = 0
    while current is not EmptyList and isinstance(current, Cons):
        current = current.cdr
        count += 1
    if current is not EmptyList:
        return handler("Attempt to take length of improper list")
    return count

def rac(item):
    current = item
    previous = None
    while current is not EmptyList:
        previous = current.car
        current = current.cdr
    return previous

## We use "_q" in Python to represent "?" in Scheme.

def pair_q(item):
    return isinstance(item, Cons)

def null_q(lst):
    return lst is EmptyList
In [32]:
def list_to_vector(lst):
    retval = []
    current = lst
    while current is not EmptyList:
        retval.append(current.car)
        current = current.cdr
    return retval

def extend_env(vars, vals, env):
    return [dict(map(list,zip(list_to_vector(vars), 
                              list_to_vector(vals)))), env]
In [33]:
extend_env(List("x", "y"), List(1, 2), [])
Out[33]:
[{'x': 1, 'y': 2}, []]